using RootMotion.FinalIK;

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;

using Unity.VisualScripting;

using UnityEngine;

namespace AluminumIngot
{
    /// <summary>
    /// 铝锭单元被控脚本
    /// </summary>
    public class AluminumIngotUnit : BPAIBase//, IAlumBlockInterface
	{
		#region 字段与访问器

		/// <summary>
		/// 是否是受到阻挡的
		/// </summary>
		public bool IsBlocked => RestainingMass != null;
		//public List<AluminumIngotUnit> BlockList => RestainingMass == null ? null : RestainingMass.BlockList;
		/// <summary>
		/// 阻挡物引用
		/// </summary>
		public IAlumBlockInterface RestainingMass;

		/// <summary>
		/// 是被持有的，持有时不响应施力与阻挡，
		/// 持有状态分为绑定持有和融合持有
		/// </summary>
		public bool IsHolding => isHolding;
		private bool isHolding = false;

		/// <summary>
		/// 设定是否退掉刚体，这会销毁刚体，需要谨慎使用
		/// </summary>
		public bool ExistRigidbody
		{
			get => rigidbody == null; 
			set 
			{
				if(value)
				{
					if(rigidbody != null)
					{
						Destroy(transform.GetComponent<Rigidbody>());
						rigidbody = null;
					}
				}
				else if(rigidbody == null)
				{
					rigidbody = transform.AddComponent<Rigidbody>();
				}
			}
		}

		/// <summary>
		/// 刚体
		/// </summary>
		private new Rigidbody rigidbody;
		/// <summary>
		/// 旧父级，用于退出绑定后的恢复
		/// </summary>
		private Transform oldParent;


		#endregion

		#region 生命周期

		protected new void Awake () 
		{
			base.Awake();
			rigidbody = transform.GetComponent<Rigidbody>();
		}

		protected void FixedUpdate()
		{
			UpdateMove();
		}

		#endregion

		#region 处理方法

		/// <summary>
		/// 移动更新方法
		/// </summary>
		protected void UpdateMove ()
		{
			// 如果不处于阻挡时或被持有状态，运动
			if(!IsBlocked || !IsHolding)
			{
				CalculatedNormalMoveFormListWithWeight();
				Vector3 move = moveDirection * this.speed;
				rigidbody.velocity = move;
			}
		}

		/// <summary>
		/// 尝试开始阻挡，如果不满足阻挡条件，就不会阻挡
		/// </summary>
		public void TryInBlocked(AluminumIngotUnit otherUnit)
		{
			// 传入空是意义不明的
			if(otherUnit == null)
				return;
			// 暂时想不出来传入自己可以干啥，但也不建议用来直接标记被阻挡，不太优雅
			if(otherUnit == this)
				return;
			else if(otherUnit.IsBlocked)
			{
				// 因为只支持被一个阻挡，所以需要检查是否已被阻挡。
				if(!this.IsBlocked && otherUnit.IsBlocked)
				{
					this.RestainingMass = otherUnit.RestainingMass;
					this.RestainingMass.BlockList.Add(this);
				}
			}
		}

		/// <summary>
		/// 尝试结束阻挡
		/// </summary>
		public void TryOutBlock(AluminumIngotUnit otherUnit)
		{
			// 传入空是意义不明的
			if(otherUnit == null)
				return;
			// 但是可以传入自己来跳过检查
			if(otherUnit == this)
				return;
			else if(!otherUnit.IsBlocked && this.IsBlocked)
			{
				// 检查对方是否为阻挡自己的物体，如果是，从中移除自己，表示自己不再收到阻挡
				if(this.RestainingMass.BlockList.Contains(this))
				{
					this.RestainingMass.BlockList.Remove(this);
				}
				// 因为只支持被一个阻挡，所以直接设置为不被阻挡
				this.RestainingMass = null;
			}
		}

		/// <summary>
		/// 尝试持有
		/// </summary>
		/// <param name="bindTarget">要持有的目标</param>
		/// <param name="strict">严格模式，要求必须处于被阻挡的状态才可以持有</param>
		/// <returns>返回是否持有成功</returns>
		public bool TryHold(BPAIBase bindTarget, bool strict = false)
		{
			if(rigidbody != null && (!IsHolding || (strict && IsBlocked && !IsHolding)))
			{
				// 背弃旧父
				this.oldParent = this.transform.parent;
				// 引接新父
				this.transform.parent = bindTarget.transform;
				// 设置为被持有
				this.isHolding = true;

				// 不论如何，允许旋转但不允许移动
				//this.FreezeRotation = false;
				//this.FreezeLocation = true;
				rigidbody.isKinematic = true;

				// 因为被持有了所以要从阻挡中退出
				RestainingMass = null;

				// 因为不再响应触碰，所以要清理列表
				unitList.Clear();

				return true;
			}
			return false;
		}

		/// <summary>
		/// 尝试释放
		/// </summary>
		/// <param name="newParent"></param>
		public void TryRelease(Transform newParent = null)
		{
			if(IsHolding)
			{
				// 要么回归旧父，要么再认新父
				transform.parent = newParent == null ? this.oldParent : newParent;
				this.isHolding = false;

				// 恢复先前锁定设定
				//RecoverFreezeRotation();
				//RecoverFreezePosition();
				rigidbody.isKinematic = false;

			}
		}

		/// <summary>
		/// 尝试融合
		/// </summary>
		public bool TryFusion(Transform newParent)
		{
			if(rigidbody != null)
			{
				// 融合需要一个目标
				transform.parent = newParent;
				//ExistRigidbody = true;
				Destroy(transform.GetComponent<Rigidbody>());
				rigidbody = null;
				//Destroy(transform.GetComponent<AluminumIngotUnit>());
				return true;
			}
			return false;
		}

		#endregion

		#region 碰撞回调

		protected void OnCollisionEnter(Collision collision)
		{
			AluminumIngotUnit otherUnit = collision.transform.GetComponent<AluminumIngotUnit>();
			if(otherUnit != null)
			{
				TryInBlocked(otherUnit);
				return;
			}
		}

		protected void OnCollisionExit(Collision collision)
		{
			AluminumIngotUnit otherUnit = collision.transform.GetComponent<AluminumIngotUnit>();
			if(otherUnit != null)
			{
				TryOutBlock(otherUnit);
			}
		}

		protected void OnTriggerEnter(Collider collider)
		{
			IAlumControlInterface target = collider.transform.GetComponent<IAlumControlInterface>();
			if(target != null)
			{
				AddWeight(target);
				unitList.Add(target);
			}
		}

		protected void OnTriggerExit(Collider collider)
		{
			IAlumControlInterface target = collider.transform.GetComponent<IAlumControlInterface>();
			if(target != null)
			{
				SubWeight(target);
				unitList.Remove(target);
			}
		}

		//public void BreakBlock(AluminumIngotUnit breakUnit)
		//{
		//	if(RestainingMass != null)
		//	{
		//		this.RestainingMass.BreakBlock(breakUnit);
		//		this.RestainingMass = null;
		//	}
		//}

		#endregion
	}
}
